package fifis.game;

import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.scene.Node;
import com.jme3.bullet.control.RigidBodyControl;
import fifis.game.common.Common;
import org.apache.log4j.Logger;

/**
 * Simple Application with default methods implemented.
 *
 * @author porfiriopartida
 */
public abstract class FGame extends SimpleApplication implements ActionListener {
    protected final static Logger log4j = Logger.getLogger(FGame.class);
    protected Node view;
    boolean clearInputs;
    protected FLogic logic;
    
    public FLogic getLogic() {
        return logic;
    }
    
    public void setLogic(FLogic logic) {
        this.logic = logic;
    }
    /**
     * Prepare the Physics Application State (jBullet)
     */
    private BulletAppState bulletAppState;
    
    public FGame() {
        this(false);
    }
    
    public FGame(boolean clearInputs) {
        this.clearInputs = clearInputs;
    }
    
    protected void initCommon() {
        bulletAppState = new BulletAppState();
        Common.getInstance().setAssetManager(assetManager);
        Common.getInstance().setRootNode(rootNode);
        Common.getInstance().setStateManager(stateManager);
        Common.getInstance().setGuiNode(guiNode);
        Common.getInstance().setBulletAppState(bulletAppState);
        Common.getInstance().setCamera(getCamera());
        Common.getInstance().setCurrentApplication(this);
    }
    
    @Override
    public final void simpleInitApp() {
        initCommon();
        if (clearInputs) {
            clearInputs();
        }
        /**
         * Set up Physics Game
         */
//        bulletAppState = new BulletAppState();
//        stateManager.attach(bulletAppState);
        simpleInitFApp();
    }
    
    @Override
    public final void simpleUpdate(float tpf) {
        logic.updateActors();
        updateFApp(tpf);
    }
    
    public abstract void updateFApp(float tpf);

    public abstract void simpleInitFApp();
    
    public Node getView() {
        return view;
    }

    /**
     * Put the view as the unique scene. Also dettach all children in rootNode
     *
     * @param view View in the root node
     */
    public void setView(Node view) {
        rootNode.detachAllChildren();
        
        this.view = view;
    }

    /**
     * Clears all input mapping, so no listeners are available for keyboard nor
     * mouse.
     */
    public final void clearInputs() {
        flyCam.setEnabled(false);
//        log4j.debug(inputManager);
        inputManager.clearMappings();
        log4j.info("INPUTS REMOVED");
    }

    /**
     * inputManager.addMapping(command, new KeyTrigger(key));
     *
     * @param command Command key value for this input like "goUp", "goDown" and
     * so on.
     * @param key com.jme3.input.KeyInput
     */
    public final void addInput(String command, int key) {
        log4j.debug("INPUT added " + command + "[ "+key+" ]");
        inputManager.addMapping(command, new KeyTrigger(key));
        inputManager.addListener(this, command);
    }
    
    public final void addMouseInput(String command, int key) {
        inputManager.addMapping(command, new MouseButtonTrigger(key));
        inputManager.addListener(this, command);
        log4j.debug("MOUSEINPUT added " + command + "[ "+key+" ]");
    }
    /**
     * Prepare Materials
     */
//    Material wall_mat;
//    Material stone_mat
//        stone_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");;
//    Material floor_mat;
    private RigidBodyControl ball_phy;
    
    @Override
    public void onAction(String name, boolean isPressed, float tpf) {
////        log4j.debug("onAction [ " + name + ", " + isPressed + ", " + tpf + "]");
//        if ("click".equals(name) && isPressed) {
//            /**
//             * Create a cannon ball geometry and attach to scene graph.
//             */
//            Geometry ball_geo = new Geometry("cannon ball", sphere);
//            ball_geo.setMaterial(stone_mat);
//            Node bulletNode = new Node();
//            bulletNode.attachChild(ball_geo);
//            MyBullet bulletActor = new MyBullet(bulletNode, getCamera().getDirection());
//            new Thread(bulletActor).start();
//            getLogic().addActor(bulletActor);
////            rootNode.attachChild(bulletNode);
//            /**
//             * Position the cannon ball
//             */
//            ball_geo.setLocalTranslation(Common.getInstance().getCamera().getLocation());
////            ball_geo.addControl(uc);
//            /**
//             * Make the ball physcial with a mass > 0.0f
//             */
////            ball_phy = new RigidBodyControl(1f);
////            ball_phy.setGravity(getCamera().getDirection());
//            /**
//             * Add physical ball to physics space.
//             */
////            ball_geo.addControl(ball_phy);
////            bulletAppState.getPhysicsSpace().add(uc);
////            bulletAppState.getPhysicsSpace().add(uc);
//            /**
//             * Accelerate the physcial ball to shoot it.
//             */
////            ball_phy.setLinearVelocity(cam.getDirection().mult(225));
//        }
        
    }

    /**
     * Prepare geometries and physical nodes for bricks and cannon balls.
     */
////    private static final Box box;
//    private static final Sphere sphere;
//    private static final Box floor;
    /**
     * dimensions used for bricks and wall
     */
//    private static final float brickLength = 0.48f;
//    private static final float brickWidth = 0.24f;
//    private static final float brickHeight = 0.12f;
//    
//    static {
//        /**
//         * Initialize the cannon ball geometry
//         */
//        sphere = new Sphere(32, 32, 0.4f, true, false);
//        sphere.setTextureMode(TextureMode.Projected);
//        /**
//         * Initialize the brick geometry
//         */
////        box = new Box(Vector3f.ZERO, brickLength, brickHeight, brickWidth);
////        box.scaleTextureCoordinates(new Vector2f(1f, .5f));
//        /**
//         * Initialize the floor geometry
//         */
////        floor = new Box(Vector3f.ZERO, 10f, 0.1f, 5f);
////        floor.scaleTextureCoordinates(new Vector2f(3, 6));
//    }

    /**
     * Initialize the materials used in this scene.
     */
//    public void initMaterials() {
////    wall_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
////    TextureKey key = new TextureKey("Textures/Terrain/BrickWall/BrickWall.jpg");
////    key.setGenerateMips(true);
////    Texture tex = assetManager.loadTexture(key);
////    wall_mat.setTexture("ColorMap", tex);
//// 
//        stone_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
////    TextureKey key2 = new TextureKey("Textures/Terrain/Rock/Rock.PNG");
////    key2.setGenerateMips(true);
////    Texture tex2 = assetManager.loadTexture(key2);
////    stone_mat.setTexture("ColorMap", tex2);
//// 
////    floor_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
////    TextureKey key3 = new TextureKey("Textures/Terrain/Pond/Pond.jpg");
////    key3.setGenerateMips(true);
////    Texture tex3 = assetManager.loadTexture(key3);
////    tex3.setWrap(WrapMode.Repeat);
////    floor_mat.setTexture("ColorMap", tex3);
//    }
}
